#include "uart_exchange.h"
#include "board.h"

static com_exchange_cb_t com_exchange_cb;

static void com_exchange_console_pre_config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
	/* Enable USART2 and GPIOA clocks */
	RCC_APB2PeriphClockCmd(COM_EXCHANGE_UART_RCC_GPIO, ENABLE);
	RCC_APB1PeriphClockCmd(COM_EXCHANGE_UART_RCC, ENABLE);


	// Configure USART2 Tx as alternate function push-pull
	GPIO_InitStructure.GPIO_Pin = COM_EXCHANGE_UART_GPIO_TX;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
	GPIO_Init(COM_EXCHANGE_UART_GPIO, &GPIO_InitStructure);
	// Configure USART2 Rx as input floating
	GPIO_InitStructure.GPIO_Pin = COM_EXCHANGE_UART_GPIO_RX;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(COM_EXCHANGE_UART_GPIO, &GPIO_InitStructure);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
	/* Enable the USART2 Interrupt */
	NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
}

void com_exchange_console_register_callback(com_exchange_cb_t cb)
{
	com_exchange_cb = cb;
}

void com_exchange_console_isr(void)
{
	unsigned char temp_Rx=0;

	if(USART_GetITStatus(COM_EXCHANGE_UART_PORT, USART_IT_RXNE) == SET)
	{
		temp_Rx = USART_ReceiveData(COM_EXCHANGE_UART_PORT);  
		raw_printf("%c", temp_Rx);

		if(com_exchange_cb != YLN_NULL)
		{
			com_exchange_cb(temp_Rx);
		}
		USART_ClearFlag(COM_EXCHANGE_UART_PORT,USART_FLAG_RXNE);
		USART_ClearITPendingBit(COM_EXCHANGE_UART_PORT,USART_IT_RXNE);
	}
}

void com_exchange_console_init(void)
{
	USART_InitTypeDef USART_InitStructure;
	USART_ClockInitTypeDef USART_ClockInitStructure;

	com_exchange_console_pre_config();

	USART_InitStructure.USART_BaudRate = COM_EXCHANGE_UART_BAUD;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	USART_ClockInitStructure.USART_Clock = USART_Clock_Disable;
	USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;
	USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge;
	USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable;
	USART_Init(COM_EXCHANGE_UART_PORT, &USART_InitStructure);
	USART_ClockInit(COM_EXCHANGE_UART_PORT, &USART_ClockInitStructure);

	com_exchange_cb = YLN_NULL;
	USART_ITConfig(COM_EXCHANGE_UART_PORT, USART_IT_RXNE, ENABLE);
	USART_Cmd(COM_EXCHANGE_UART_PORT, ENABLE);
}

void com_exchange_console_put_byte(unsigned char ch)
{
	unsigned short err = 0xffff;
	/* Wait until end of transmit */
	while((USART_GetFlagStatus(COM_EXCHANGE_UART_PORT, USART_FLAG_TXE) == RESET)&&(err--))
	{
	}
	/* Write one byte in the USART1 Transmit Data Register */
	USART_SendData(COM_EXCHANGE_UART_PORT, ch);
}

void exchange_printf(unsigned char *data, unsigned int len)
{
	unsigned int i = 0;
	for(i = 0; i < len; i++)
	{
		com_exchange_console_put_byte(data[i]);
	}
}
